package cn.waleychain.exchange.service.impl.wallet.listener;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.Date;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import cn.waleychain.exchange.core.constant.DDIC;
import cn.waleychain.exchange.core.logger.LoggerHelper;
import cn.waleychain.exchange.core.utils.SequenceUtils;
import cn.waleychain.exchange.feign.CoinServiceFeign;
import cn.waleychain.exchange.model.CoinInfo;
import cn.waleychain.exchange.model.CoinWallet;
import cn.waleychain.exchange.model.CoinWalletChange;
import cn.waleychain.exchange.model.WalletRecharge;
import cn.waleychain.exchange.service.impl.wallet.ethtoken.EthToken.TransferEventResponse;
import cn.waleychain.exchange.service.impl.wallet.utils.EthTokenCoinClient;
import cn.waleychain.exchange.service.wallet.CoinWalletService;
import rx.functions.Action1;

public class EthTokenReceiveListener implements Action1<TransferEventResponse> {
	
	private static final Logger mLog = LoggerFactory.getLogger(EthReceiveListenerTwo.class);
	
    private CoinServiceFeign coinFeign;
    private CoinWalletService coinWalletService;
    private long coinId;
    private String coinName;
    private int lastBlockNumber;

    public EthTokenReceiveListener(long coinId, CoinServiceFeign coinFeign, CoinWalletService coinWalletService) {
        this(coinId, "unknow(" + coinId + ")", 0, coinFeign, coinWalletService);
    }

    public EthTokenReceiveListener(long coinId, String coinName, int sinceBlockNumber, CoinServiceFeign coinFeign, CoinWalletService coinWalletService) {
        this.coinId = coinId;
        this.coinName = coinName;
        this.lastBlockNumber = sinceBlockNumber;
        this.coinFeign = coinFeign;
        this.coinWalletService = coinWalletService;

        LoggerHelper.printLogInfo(mLog, coinName + " receive listener");
    }

    public void call(TransferEventResponse t) {
        try {
            CoinInfo tradeCoin = this.coinFeign.fetchCoinById(this.coinId);
            if (tradeCoin == null) {
                return;
            }

            int currentBlockNumber = t.log.getBlockNumber().intValue();
            CoinWallet userEth = this.coinWalletService.fetchWalletByCoinIdAndAddr(this.coinId, t._to.toString());
            if (userEth != null && t._value.compareTo(BigInteger.ZERO) > 0) {
                String txid = t.log.getTransactionHash();
                WalletRecharge userInWallet = coinWalletService.fetchWalletRechargeByTxIdAndAddress(txid, userEth.getAddress());
                if (userInWallet == null) {
                    BigDecimal amount = (new BigDecimal(t._value)).divide(EthTokenCoinClient.decimal.get(tradeCoin.getName()));
                    
                    WalletRecharge inRecord = new WalletRecharge();
                    inRecord.setIdNo(SequenceUtils.generateDefaultSerialNum());
                    inRecord.setCoinWalletId(userEth.getCoinWalletId());
                    inRecord.setAddress(t._to.toString());
                    inRecord.setAmount(amount);
                    inRecord.setFee(new BigDecimal("0"));
                    inRecord.setRealAmount(amount);
                    inRecord.setTxId(txid);
                    inRecord.setStatus(-12);
                    
                    CoinWalletChange change = new CoinWalletChange();
                    change.setCoinWalletId(userEth.getCoinWalletId());
                    change.setBizType(DDIC.WalletBizType.WALLET_RECHARGE.id);
                    change.setBizTypeId(inRecord.getIdNo());
                    change.setType(DDIC.AccountChangeType.INCOME_1.id);
                    change.setStatus(DDIC.WalletChangeStatus.RECHARGE_SUSS.id);
                    change.setCreateTime(new Date());
                    
                    if (this.coinWalletService.addWalletRecharge(inRecord, change)) {
                    	LoggerHelper.printLogInfo(mLog, "[" + this.coinName + "]receiveConfirmed");
                    }
                    
                }
            }

            if (currentBlockNumber > this.lastBlockNumber) {
                this.lastBlockNumber = currentBlockNumber;
                CoinInfo coin = new CoinInfo();
                coin.setCoinId(this.coinId);
                coin.setLastblock(currentBlockNumber + "");
                this.coinFeign.modifyCoinInfo(coin);
            }
        } catch (Exception e) {
            e.printStackTrace();
            LoggerHelper.printLogErrorNotThrows(mLog, e, this.coinName + " receive error:" + e.getMessage());
        }

    }
}
